home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 002 / emacssrc.arc / SPAWN.C < prev    next >
C/C++ Source or Header  |  1987-02-04  |  17KB  |  639 lines

  1. /*    Spawn:    various DOS access commands
  2.         for MicroEMACS
  3. */
  4.  
  5. #include        <stdio.h>
  6. #include    "estruct.h"
  7. #include        "edef.h"
  8.  
  9. #if     AMIGA
  10. #define  NEW   1006
  11. #endif
  12.  
  13. #if        ST520 & MEGAMAX
  14. #include <osbind.h>
  15. #include <string.h>
  16. #define LOAD_EXEC 0     /* load and execute the program */
  17. char    *STcmd,        /* the command filename & path  */
  18.     *STargs,    /* command args (if any)        */
  19.     *STenv,        /* environment                  */
  20.     *STwork;    /* work area            */
  21. #endif
  22.  
  23. #if     VMS
  24. #define EFN     0                               /* Event flag.          */
  25.  
  26. #include        <ssdef.h>                       /* Random headers.      */
  27. #include        <stsdef.h>
  28. #include        <descrip.h>
  29. #include        <iodef.h>
  30.  
  31. extern  int     oldmode[3];                     /* In "termio.c"        */
  32. extern  int     newmode[3];                     /* In "termio.c"        */
  33. extern  short   iochan;                         /* In "termio.c"        */
  34. #endif
  35.  
  36. #if     V7 | USG | BSD
  37. #include        <signal.h>
  38. extern int vttidy();
  39. #endif
  40.  
  41. #if    MSDOS & MSC
  42. #include    <process.h>
  43. #define    system(a)    spawnlp(P_WAIT, a, NULL)
  44. #endif
  45.  
  46. /*
  47.  * Create a subjob with a copy of the command intrepreter in it. When the
  48.  * command interpreter exits, mark the screen as garbage so that you do a full
  49.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  50.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  51.  */
  52. spawncli(f, n)
  53. {
  54. #if     AMIGA
  55.         long newcli;
  56. #endif
  57.  
  58. #if     V7 | USG | BSD
  59.         register char *cp;
  60.         char    *getenv();
  61. #endif
  62.  
  63.     /* don't allow this command if restricted */
  64.     if (restflag)
  65.         return(resterr());
  66.  
  67. #if    AMIGA
  68.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  69.         mlwrite("[Starting new CLI]");
  70.         sgarbf = TRUE;
  71.         Execute("", newcli, 0);
  72.         Close(newcli);
  73.         return(TRUE);
  74. #endif
  75.  
  76. #if     VMS
  77.         movecursor(term.t_nrow, 0);             /* In last line.        */
  78.         mlputs("[Starting DCL]\r\n");
  79.         TTflush();                          /* Ignore "ttcol".      */
  80.         sgarbf = TRUE;
  81.         return (sys(NULL));                     /* NULL => DCL.         */
  82. #endif
  83. #if     CPM
  84.         mlwrite("Not in CP/M-86");
  85. #endif
  86. #if    ST520
  87.     mlwrite("Not in TOS");
  88. #endif
  89. #if     MSDOS & AZTEC
  90.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  91.         TTflush();
  92.     TTkclose();
  93.     system("command.com");
  94.     TTkopen();
  95.         sgarbf = TRUE;
  96.         return(TRUE);
  97. #endif
  98. #if     MSDOS & LATTICE
  99.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  100.         TTflush();
  101.     TTkclose();
  102.         sys("\\command.com", "");               /* Run CLI.             */
  103.     TTkopen();
  104.         sgarbf = TRUE;
  105.         return(TRUE);
  106. #endif
  107. #if     V7 | USG | BSD
  108.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  109.         TTflush();
  110.         TTclose();                              /* stty to old settings */
  111.         if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  112.                 system(cp);
  113.         else
  114. #if    BSD
  115.                 system("exec /bin/csh");
  116. #else
  117.                 system("exec /bin/sh");
  118. #endif
  119.         sgarbf = TRUE;
  120.         sleep(2);
  121.         TTopen();
  122.         return(TRUE);
  123. #endif
  124. }
  125.  
  126. #if    BSD
  127.  
  128. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  129. {
  130.     int pid;
  131.  
  132.     vttidy();
  133.     pid = getpid();
  134.     kill(pid,SIGTSTP);
  135. }
  136.  
  137. rtfrmshell()
  138. {
  139.     TTopen();
  140.     curwp->w_flag = WFHARD;
  141.     sgarbf = TRUE;
  142. }
  143. #endif
  144.  
  145. /*
  146.  * Run a one-liner in a subjob. When the command returns, wait for a single
  147.  * character to be typed, then mark the screen as garbage so a full repaint is
  148.  * done. Bound to "C-X !".
  149.  */
  150. spawn(f, n)
  151. {
  152.         register int    s;
  153.         char            line[NLINE];
  154.  
  155. #if    ST520 & MEGAMAX
  156.     int i,j,k;
  157.     char *sptr,*tptr;
  158. #endif
  159.  
  160. #if     AMIGA
  161.         long newcli;
  162. #endif
  163.  
  164.     /* don't allow this command if restricted */
  165.     if (restflag)
  166.         return(resterr());
  167.  
  168. #if    AMIGA
  169.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  170.                 return (s);
  171.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  172.         Execute(line,0,newcli);
  173.         Close(newcli);
  174.         tgetc();     /* Pause.               */
  175.         sgarbf = TRUE;
  176.         return(TRUE);
  177. #endif
  178. #if     ST520 & MEGAMAX
  179.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  180.                 return(s);
  181.     movecursor(term.t_nrow - 1, 0);
  182.     TTclose();
  183. /*
  184.  * break the line into the command and its args
  185.  * be cute about it, if there is no '.' in the filename, try
  186.  * to find .prg, .tos or .ttp in that order
  187.  * in any case check to see that the file exists before we run 
  188.  * amok
  189.  */
  190.     STenv = NULL;
  191.     if((tptr = index(&line[0],' ')) == NULL) { /* no args */
  192.         STcmd = (char *)malloc(strlen(line) + 1);
  193.         strcpy(STcmd,line);
  194.         STargs = NULL;
  195.     }
  196.     else {  /* seperate out the args from the command */
  197.         /* resist the temptation to do ptr arithmetic */
  198.         STcmd = (char *)malloc(strlen(line) + 1);
  199.         for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++)
  200.             STcmd[i] = *sptr;
  201.         STcmd[i] = '\0';
  202.         for(; *tptr == ' ' || *tptr == '\t'; tptr++);
  203.         if(*tptr == '\0')
  204.             STargs = NULL;
  205.         else {
  206.             STargs = (char *)malloc(strlen(tptr) + 2);
  207. /* first byte of STargs is the length of the string */
  208.             STargs[0] = strlen(tptr);
  209.             STargs[1] = NULL; /* fake it for strcat */
  210.             strcat(STargs,tptr);
  211.         }
  212.     }
  213. /*
  214.  * before we issue the command look for the '.', if it's not there
  215.  * try adding .prg, .tos and .ttp to see if they exist, if not
  216.  * issue the command as is
  217.  */
  218.     if((tptr = index(STcmd,'.')) == NULL) {
  219.          STwork = (char *)malloc(strlen(STcmd) + 4);
  220.          strcpy(STwork,STcmd);
  221.          strcat(STwork,".prg");
  222.          tptr = index(STwork,'.');
  223.          if(Fsfirst(1,STwork) != 0) { /* try .tos */
  224.              strcpy(tptr,".tos");
  225.              if(Fsfirst(1,STwork) != 0) { /* try .ttp */
  226.                  strcpy(tptr,".ttp");
  227.                  if(Fsfirst(1,STwork) != 0) /* never mind */
  228.                      *STwork = NULL;
  229.                  }
  230.              }
  231.      }
  232.      if(*STwork != NULL)
  233.             Pexec(LOAD_EXEC,STwork,STargs,STenv);         
  234.     else
  235.             Pexec(LOAD_EXEC,STcmd,STargs,STenv);
  236.     TTopen();
  237.         mlputs("\r\n\n[End]");                  /* Pause.               */
  238.         TTgetc();                 /* Pause.               */
  239.         sgarbf = TRUE;
  240.         return (TRUE);
  241. #endif
  242. #if     VMS
  243.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  244.                 return (s);
  245.         TTputc('\n');                /* Already have '\r'    */
  246.         TTflush();
  247.         s = sys(line);                          /* Run the command.     */
  248.         mlputs("\r\n\n[End]");                  /* Pause.               */
  249.         TTflush();
  250.         tgetc();
  251.         sgarbf = TRUE;
  252.         return (s);
  253. #endif
  254. #if     CPM
  255.         mlwrite("Not in CP/M-86");
  256.         return (FALSE);
  257. #endif
  258. #if     MSDOS | (ST520 & LATTICE)
  259.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  260.                 return(s);
  261.     movecursor(term.t_nrow - 1, 0);
  262.     TTkclose();
  263.         system(line);
  264.     TTkopen();
  265.     /* if we are interactive, pause here */
  266.     if (clexec == FALSE) {
  267.             mlputs("\r\n\n[End]");
  268.             tgetc();
  269.         }
  270.         sgarbf = TRUE;
  271.         return (TRUE);
  272. #endif
  273. #if     V7 | USG | BSD
  274.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  275.                 return (s);
  276.         TTputc('\n');                /* Already have '\r'    */
  277.         TTflush();
  278.         TTclose();                              /* stty to old modes    */
  279.         system(line);
  280.         TTopen();
  281.         mlputs("[End]");                        /* Pause.               */
  282.         TTflush();
  283.         while ((s = tgetc()) != '\r' && s != ' ')
  284.                 ;
  285.         sgarbf = TRUE;
  286.         return (TRUE);
  287. #endif
  288. }
  289.  
  290. /*
  291.  * Pipe a one line command into a window
  292.  * Bound to ^X @
  293.  */
  294. pipe(f, n)
  295. {
  296.         register int    s;    /* return status from CLI */
  297.     register WINDOW *wp;    /* pointer to new window */
  298.     register BUFFER *bp;    /* pointer to buffer to zot */
  299.         char    line[NLINE];    /* command line send to shell */
  300.     static char bname[] = "command";
  301.  
  302. #if    AMIGA
  303.     static char filnam[] = "ram:command";
  304.         long newcli;
  305. #else
  306.     static char filnam[] = "command";
  307. #endif
  308.  
  309. #if    MSDOS
  310.     char *tmp;
  311.     char *getenv();
  312.     FILE *fp;
  313.     FILE *fopen();
  314. #endif
  315.  
  316.     /* don't allow this command if restricted */
  317.     if (restflag)
  318.         return(resterr());
  319.  
  320. #if    MSDOS
  321.     if ((tmp = getenv("TMP")) == NULL)
  322.         strcpy(filnam, "command");
  323.     else
  324.         strcpy(filnam, tmp);
  325. #endif
  326.  
  327. #if     VMS
  328.     mlwrite("Not availible under VMS");
  329.     return(FALSE);
  330. #endif
  331. #if     CPM
  332.         mlwrite("Not availible under CP/M-86");
  333.         return(FALSE);
  334. #endif
  335.  
  336.     /* get the command to pipe in */
  337.         if ((s=mlreply("@", line, NLINE)) != TRUE)
  338.                 return(s);
  339.  
  340.     /* get rid of the command output buffer if it exists */
  341.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  342.         /* try to make sure we are off screen */
  343.         wp = wheadp;
  344.         while (wp != NULL) {
  345.             if (wp->w_bufp == bp) {
  346.                 onlywind(FALSE, 1);
  347.                 break;
  348.             }
  349.             wp = wp->w_wndp;
  350.         }
  351.         if (zotbuf(bp) != TRUE)
  352.             return(FALSE);
  353.     }
  354.  
  355. #if     AMIGA
  356.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  357.     strcat(line, " >");
  358.     strcat(line, filnam);
  359.         Execute(line,0,newcli);
  360.     s = TRUE;
  361.         Close(newcli);
  362.         sgarbf = TRUE;
  363. #endif
  364. #if     MSDOS
  365.     strcat(line," >>");
  366.     strcat(line,filnam);
  367.     movecursor(term.t_nrow - 1, 0);
  368.     TTkclose();
  369.         system(line);
  370.     TTkopen();
  371.         sgarbf = TRUE;
  372.     if ((fp = fopen(filnam, "r")) == NULL) {
  373.         s = FALSE;
  374.     } else {
  375.         fclose(fp);
  376.         s = TRUE;
  377.     }
  378. #endif
  379. #if     V7 | USG | BSD
  380.         TTputc('\n');                /* Already have '\r'    */
  381.         TTflush();
  382.         TTclose();                              /* stty to old modes    */
  383.     strcat(line,">");
  384.     strcat(line,filnam);
  385.         system(line);
  386.         TTopen();
  387.         TTflush();
  388.         sgarbf = TRUE;
  389.         s = TRUE;
  390. #endif
  391.  
  392.     if (s != TRUE)
  393.         return(s);
  394.  
  395.     /* split the current window to make room for the command output */
  396.     if (splitwind(FALSE, 1) == FALSE)
  397.             return(FALSE);
  398.  
  399.     /* and read the stuff in */
  400.     if (getfile(filnam, FALSE) == FALSE)
  401.         return(FALSE);
  402.  
  403.     /* make this window in VIEW mode, update all mode lines */
  404.     curwp->w_bufp->b_mode |= MDVIEW;
  405.     wp = wheadp;
  406.     while (wp != NULL) {
  407.         wp->w_flag |= WFMODE;
  408.         wp = wp->w_wndp;
  409.     }
  410.  
  411.     /* and get rid of the temporary file */
  412.     unlink(filnam);
  413.     return(TRUE);
  414. }
  415.  
  416. /*
  417.  * filter a buffer through an external DOS program
  418.  * Bound to ^X #
  419.  */
  420. filter(f, n)
  421.  
  422. {
  423.         register int    s;    /* return status from CLI */
  424.     register BUFFER *bp;    /* pointer to buffer to zot */
  425.         char line[NLINE];    /* command line send to shell */
  426.     char tmpnam[NFILEN];    /* place to store real file name */
  427.     static char bname1[] = "fltinp";
  428.  
  429. #if    AMIGA
  430.     static char filnam1[] = "ram:fltinp";
  431.     static char filnam2[] = "ram:fltout";
  432.         long newcli;
  433. #else
  434.     static char filnam1[] = "fltinp";
  435.     static char filnam2[] = "fltout";
  436. #endif
  437.  
  438.     /* don't allow this command if restricted */
  439.     if (restflag)
  440.         return(resterr());
  441.  
  442.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  443.         return(rdonly());    /* we are in read only mode    */
  444.  
  445. #if     VMS
  446.     mlwrite("Not availible under VMS");
  447.     return(FALSE);
  448. #endif
  449. #if     CPM
  450.         mlwrite("Not availible under CP/M-86");
  451.         return(FALSE);
  452. #endif
  453.  
  454.     /* get the filter name and its args */
  455.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  456.                 return(s);
  457.  
  458.     /* setup the proper file names */
  459.     bp = curbp;
  460.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  461.     strcpy(bp->b_fname, bname1);    /* set it to our new one */
  462.  
  463.     /* write it out, checking for errors */
  464.     if (writeout(filnam1) != TRUE) {
  465.         mlwrite("[Cannot write filter file]");
  466.         strcpy(bp->b_fname, tmpnam);
  467.         return(FALSE);
  468.     }
  469.  
  470. #if     AMIGA
  471.         newcli = Open("CON:1/1/639/199/MicroEmacs Subprocess", NEW);
  472.     strcat(line, " <ram:fltinp >ram:fltout");
  473.         Execute(line,0,newcli);
  474.     s = TRUE;
  475.         Close(newcli);
  476.         sgarbf = TRUE;
  477. #endif
  478. #if     MSDOS
  479.     strcat(line," <fltinp >fltout");
  480.     movecursor(term.t_nrow - 1, 0);
  481.     TTkclose();
  482.         system(line);
  483.     TTkopen();
  484.         sgarbf = TRUE;
  485.     s = TRUE;
  486. #endif
  487. #if     V7 | USG | BSD
  488.         TTputc('\n');                /* Already have '\r'    */
  489.         TTflush();
  490.         TTclose();                              /* stty to old modes    */
  491.     strcat(line," <fltinp >fltout");
  492.         system(line);
  493.         TTopen();
  494.         TTflush();
  495.         sgarbf = TRUE;
  496.         s = TRUE;
  497. #endif
  498.  
  499.     /* on failure, escape gracefully */
  500.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  501.         mlwrite("[Execution failed]");
  502.         strcpy(bp->b_fname, tmpnam);
  503.         unlink(filnam1);
  504.         unlink(filnam2);
  505.         return(s);
  506.     }
  507.  
  508.     /* reset file name */
  509.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  510.     bp->b_flag |= BFCHG;        /* flag it as changed */
  511.  
  512.     /* and get rid of the temporary file */
  513.     unlink(filnam1);
  514.     unlink(filnam2);
  515.     return(TRUE);
  516. }
  517.  
  518. #if     VMS
  519. /*
  520.  * Run a command. The "cmd" is a pointer to a command string, or NULL if you
  521.  * want to run a copy of DCL in the subjob (this is how the standard routine
  522.  * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
  523.  * and the way out, because DCL does not want the channel to be in raw mode.
  524.  */
  525. sys(cmd)
  526. register char   *cmd;
  527. {
  528.         struct  dsc$descriptor  cdsc;
  529.         struct  dsc$descriptor  *cdscp;
  530.         long    status;
  531.         long    substatus;
  532.         long    iosb[2];
  533.  
  534.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  535.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  536.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  537.                 return (FALSE);
  538.         cdscp = NULL;                           /* Assume DCL.          */
  539.         if (cmd != NULL) {                      /* Build descriptor.    */
  540.                 cdsc.dsc$a_pointer = cmd;
  541.                 cdsc.dsc$w_length  = strlen(cmd);
  542.                 cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  543.                 cdsc.dsc$b_class   = DSC$K_CLASS_S;
  544.                 cdscp = &cdsc;
  545.         }
  546.         status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
  547.         if (status != SS$_NORMAL)
  548.                 substatus = status;
  549.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  550.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  551.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  552.                 return (FALSE);
  553.         if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
  554.                 return (FALSE);
  555.         return (TRUE);
  556. }
  557. #endif
  558.  
  559. #if    ~AZTEC & MSDOS
  560.  
  561. /*
  562.  * This routine, once again by Bob McNamara, is a C translation of the "system"
  563.  * routine in the MWC-86 run time library. It differs from the "system" routine
  564.  * in that it does not unconditionally append the string ".exe" to the end of
  565.  * the command name. We needed to do this because we want to be able to spawn
  566.  * off "command.com". We really do not understand what it does, but if you don't
  567.  * do it exactly "malloc" starts doing very very strange things.
  568.  */
  569. sys(cmd, tail)
  570. char    *cmd;
  571. char    *tail;
  572. {
  573. #if MWC_86
  574.         register unsigned n;
  575.         extern   char     *__end;
  576.  
  577.         n = __end + 15;
  578.         n >>= 4;
  579.         n = ((n + dsreg() + 16) & 0xFFF0) + 16;
  580.         return(execall(cmd, tail, n));
  581. #endif
  582.  
  583. #if LATTICE
  584.         return(forklp(cmd, tail, (char *)NULL));
  585. #endif
  586.  
  587. #if    MSC
  588.     return(spawnlp(P_WAIT, cmd, tail, NULL));
  589. #endif
  590. }
  591. #endif
  592.  
  593. #if    MSDOS & LATTICE
  594. /*    System: a modified version of lattice's system() function
  595.         that detects the proper switchar and uses it
  596.         written by Dana Hogget                */
  597.  
  598. system(cmd)
  599.  
  600. char *cmd;    /*  Incoming command line to execute  */
  601.  
  602. {
  603.     char *getenv();
  604.     static char *swchar = "/C";    /*  Execution switch  */
  605.     union REGS inregs;    /*  parameters for dos call  */
  606.     union REGS outregs;    /*  Return results from dos call  */
  607.     char *shell;        /*  Name of system command processor  */
  608.     char *p;        /*  Temporary pointer  */
  609.     int ferr;        /*  Error condition if any  */
  610.  
  611.     /*  get name of system shell  */
  612.     if ((shell = getenv("COMSPEC")) == NULL) {
  613.         return (-1);        /*  No shell located  */
  614.     }
  615.  
  616.     p = cmd;
  617.     while (isspace(*p)) {        /*  find out if null command */
  618.         p++;
  619.     }
  620.  
  621.     /**  If the command line is not empty, bring up the shell  **/
  622.     /**  and execute the command.  Otherwise, bring up the     **/
  623.     /**  shell in interactive mode.   **/
  624.  
  625.     if (p && *p) {
  626.         /**  detect current switch character and us it  **/
  627.         inregs.h.ah = 0x37;    /*  get setting data  */
  628.         inregs.h.al = 0x00;    /*  get switch character  */
  629.         intdos(&inregs, &outregs);
  630.         *swchar = outregs.h.dl;
  631.         ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
  632.     } else {
  633.         ferr = forkl(shell, "command", (char *)NULL);
  634.     }
  635.  
  636.     return (ferr ? ferr : wait());
  637. }
  638. #endif
  639.